package memorytrace.tools

import java.lang._
import java.io._
import scala.collection.mutable._
import scala.actors.Actor._

object SymboleTables {

  
  /**
   * table des symboles de l'exécutable instrumenté
   */
  private var table_symbs : HashMap [String,String]= new HashMap[String,String]
  
  /**
   * symboles brutes extraits à partir de l'exécutable
   */
  private var symbs : ListBuffer[String]=new ListBuffer[String]
  
  
  /**
   * liste des classes c++ de l'exécutable
   */
  private var classes: List[String] =null
  
  /**
   * liste des fonction c/c++ de l'exécutable
   */
  private var functions: List[String]=null
  
  /**
   * liste des adresses des symboles c/c++
   */
  private var addrs: List[String]=null
  
  
  /**
   * retourne la liste des symboles de l'exécutbale
   */
  def getFunctions()={
    if(functions==null){
      functions=table_symbs.map(s=>s._2).toList
    }
    functions
  }
  
  /**
   * retourne la liste des classes de l'exécutable
   */
  def getClasses()={
    if(classes==null){
    	classes=table_symbs.map(x => x._2.split("::")(0)).toList
    }
    classes
  }
  
  /**
   * retourne la liste des adresses des symboles
   */
  def getAdresses()={
    if(addrs==null){
      addrs = table_symbs.map(s=>s._1).toList.removeDuplicates.remove(s=> (s==""))
    }
    addrs
  }
  /**
   * Créer un acteur qui construire la map
   */
  def createMap()={    
	
    symbs.foreach(
        s=> {
        		val tokens = s.split(" ",3)
        		/*insere l'association tk0,tk2 dans la map*/
        		this.table_symbs+=tokens(0)->tokens(2)
        	}
      )
    /*traitement des symboles*/
	//this.table_symbs.foreach(x=>println(x._1 + "|**|" + x._2))
    }

  
  /**
   * Lit la table des symboles grâce à l'acteur
   */
  def readTextSegment(file:String)={
    var line:String = ""
	
    /*execution de la commande nm*/
	val proc =Runtime.getRuntime().exec(Array("nm","--demangle",file))
	
	/*on attend la fin du processus*/
	//proc.wait()
	proc.waitFor()
	/*on traite la sortie du processus*/
	if(proc.exitValue()!=0){
	  println("Fichier inexistant")
	}
	else{
		/*recuperation de la sortie de la commande*/
		val reader:BufferedReader = new BufferedReader(new InputStreamReader(proc.getInputStream()))
		
		   do {
			    line = reader.readLine()
			    if(line!=null){
			    	this.symbs+=line
			    }
			 }while(line!=null)
	}	 
  }
  
  

  /**
   * Programme principal
   */
	def buildTables(args: Array[String])  = {
	    if(args.length!=1){
	      println("Usage: scala Shell [exec file]")
	    }
		else{
		    
		    /*traitment de la sortie de la commande nm*/
		    readTextSegment(args(0))
		    
		    /*création de l'acteur mappeur*/
		    createMap();
		    
		    /*tests*/
		    //this.getClasses().foreach(println)
		    //this.getFunctions().foreach(println)
		    this.getAdresses().foreach(addr => {  var x = Long.parseLong(addr,16); println("@:"+addr+"val:"+x)})
	}
  }
}